Skip to content

Port schedule-posts.py to pulumi-social-core wrapper#18667

Merged
adamgordonbell merged 2 commits intomasterfrom
port/social-core-adoption
Apr 24, 2026
Merged

Port schedule-posts.py to pulumi-social-core wrapper#18667
adamgordonbell merged 2 commits intomasterfrom
port/social-core-adoption

Conversation

@adamgordonbell
Copy link
Copy Markdown
Contributor

Summary

Refactor scripts/social/schedule-posts.py from a 1054-line monolith into a ~180-line wrapper that imports shared scheduling logic from pulumi-social-core (https://github.com/pulumi/social@v0.1.0) as a uv git-dep. Eliminates drift between the copies in pulumi/docs and pulumi/social.

What the wrapper owns

  • Account/API-target config (PROD_MODE, USER, LINKEDIN_PAGE_ID, SITE_URL)
  • build_entries callback — parses Hugo frontmatter, derives slug + URL, resolves meta.png/meta.jpg for LinkedIn media attachments
  • CLI dispatcher (--post, --check, default schedule mode)

What moved to social_core

S3 state, upload-post.com API calls, PR comments, per-platform payload construction, char-limit detection, PR-number lookup, retries/abandonment, step summaries, failure-summary file.

Net diff

  • scripts/social/schedule-posts.py: -955 lines, +80 lines (1054 → 179 lines)

Pre-merge validation (performed locally)

  • uv resolves pulumi-social-core @ git+https://github.com/pulumi/social.git@v0.1.0 cleanly (14 packages installed).
  • DRY_RUN parity against monolith on 21 blog posts — same scheduling decisions (0 posts posted), cosmetic stdout differences only.
  • --check parity against origin/master~50 — same posts identified, same per-platform char counts and copy.
  • --post parity on synthetic test post — identical payload shape on all three platforms.
  • Live end-to-end against pulumi-test accounts — Bluesky, X, and LinkedIn each successfully posted via the wrapper path (one test post per platform, test posts visible on the pulumi-test* accounts).

CI / authentication notes

  • uv resolves the private git-dep using PULUMI_BOT_TOKEN via the existing git config url."https://x-access-token:${TOKEN}@github.com/".insteadOf "https://github.com/" pattern in both schedule-social.yml and claude-social-review.yml. No workflow changes needed — same uv run entrypoint.
  • PROD_MODE = False preserved (matches current master behavior; docs posts go to pulumi-test accounts).

Test plan

  • claude-social-review.yml runs on this PR — validates --check mode + uv git-dep resolution in CI.
  • After merge, the first schedule-social.yml run on master exercises full schedule mode end-to-end.

Follow-ups (not blocking)

  • Minor: social_core.run_post_file returns 0 even when a platform's copy is over the limit; the monolith exited 1. Only affects interactive --post use (no CI path uses --post). Can patch via social_core v0.1.1 if desired.

🤖 Generated with Claude Code

Refactor the 1054-line monolith into a ~180-line wrapper that imports
shared scheduling logic from pulumi-social-core (pulumi/social@v0.1.0)
as a uv git-dep.

The wrapper owns only docs-specific concerns:
- Account/API-target config (PROD_MODE, USER, LINKEDIN_PAGE_ID, SITE_URL)
- build_entries callback — parses Hugo frontmatter, derives slug/URL,
  resolves meta.png for LinkedIn media attachments
- CLI dispatcher (--post, --check, default schedule mode)

Everything else — S3 state, upload-post.com API calls, PR comments,
per-platform payload construction, char-limit detection, PR-number
lookup, retries/abandonment, step summaries, failure summary file —
now lives in social_core. This eliminates drift between pulumi/docs
and pulumi/social copies.

Net: -955 lines removed, +80 added in this file; total 179 lines.

Validation performed locally before merging:
- uv resolves pulumi-social-core git-dep (14 packages installed)
- DRY_RUN parity against monolith on 21 blog posts — same scheduling
  decisions, cosmetic stdout differences only
- --check parity against origin/master~50 — same posts identified,
  same per-platform char counts and copy
- --post parity on synthetic post — identical payload shape on all
  three platforms
- Live end-to-end against pulumi-test accounts: Bluesky, X, and
  LinkedIn each successfully posted via the wrapper path
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 23, 2026

Review summary

This is a thorough refactor: 1054-line monolith → 179-line wrapper, with detailed pre-merge validation (DRY_RUN parity, --check parity, --post parity on synthetic post, and live E2E against test accounts). PR body is exemplary — captures what moved, what the wrapper owns, auth flow, and known follow-ups.

The change is infrastructure code (scripts/social/schedule-posts.py), not docs content, so style-guide/markdown checks don't apply. Review below focuses on correctness and risk.

Observations

  1. Known behavior regression captured as follow-up (noted in PR body, acceptable): social_core.run_post_file exits 0 on over-limit copy where the monolith exited 1. Worth confirming nothing in the claude-social-review.yml path invokes --post (PR body says no CI path uses --post, which matches — the CI path is --check). Fine to defer to social_core v0.1.1.

  2. Docstring discrepancy in build_entries (scripts/social/schedule-posts.py:58-66, approximate lines in the new file): the docstring says "Always returns an entry per existing file, even when social copy is missing — downstream run_check emits a structured 'NO social copy' marker that the PR-review CI depends on." That contract is important and lives across two repos now. Consider:

    • Adding a comment linking to the exact social_core function that consumes an empty platforms dict, so the contract is traceable from here.
    • Or pinning this behavior with a test in pulumi/social (social_core's responsibility, not this PR's).
  3. Dependency pinning: pulumi-social-core @ git+https://github.com/pulumi/social.git@v0.1.0 — pinned to a tag, good. Note that git tags are mutable; if immutability matters, consider pinning to the commit SHA. Low risk for a first cut.

  4. Private dep + local dev ergonomics: Running this script locally now requires access to pulumi/social. The CI auth path (PULUMI_BOT_TOKEN via git config url...insteadOf) is well documented. If developers need to run this locally (e.g., for the --post one-off flow), they'll need the same insteadOf config or SSH access. A one-liner in a README or comment at the top of the script pointing to the setup would save future debugging.

  5. BUILD-AND-DEPLOY.md (lines 1382–1414 cover schedule-social.yml): the external-facing behavior is unchanged, so no update is strictly required. If you want to, a single line noting "Core logic lives in https://github.com/pulumi/social (pulumi-social-core); this workflow's script is a docs-specific wrapper" would help future maintainers find the real implementation.

  6. CLI --platform help text now reads "Limit to specific platform(s) (can be repeated; --post only)" — good improvement, matches the actual behavior (it's passed only to run_post_file).

  7. Minor — removed imports: from __future__ import annotations was dropped. Fine under uv run with a modern Python, but if the script ever runs outside uv's managed interpreter, list[str] | None etc. requires Python 3.10+. The # /// script metadata should pin requires-python if it doesn't already (not visible in the diff context).

Verdict

Solid refactor. The validation matrix in the PR body (DRY_RUN parity, check parity, post parity, live E2E) is what makes this mergeable despite touching ~1000 lines. The single behavior regression is captured as a non-blocking follow-up on the right side of the boundary.

No blocking issues from a docs-review perspective. Recommend proceeding once claude-social-review.yml runs green on this PR (test-plan item #1).


Mention @claude if you'd like another pass or fixes applied.

The refactored schedule-posts.py pulls social_core as a uv git-dep from
pulumi/social (private). Without credentials, uv's git clone fails with
"could not read Username for https://github.com: terminal prompts disabled".

Add a setup step after setup-uv in both workflows that configures
git's insteadOf with PULUMI_BOT_TOKEN from the existing ESC environment,
matching the standard pattern used elsewhere for private-repo access.
@github-actions
Copy link
Copy Markdown
Contributor

Social Media Review

No blog posts with social copy found in this PR — it's a code change, not a content change. Nothing to review.

@pulumi-bot
Copy link
Copy Markdown
Collaborator

pulumi-bot commented Apr 23, 2026

@adamgordonbell adamgordonbell merged commit 136e4a4 into master Apr 24, 2026
8 checks passed
@adamgordonbell adamgordonbell deleted the port/social-core-adoption branch April 24, 2026 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants